const path = require("path");
const fs = require("fs");
const { getAudioDuration, FFMPEG_PATH } = require("../../src/utils/ffmpeg.js");
const { mergeAudioVideo, mergeAssVideo } = require("../../src/utils/videoProcessor.js");
const { generateASSStylesSingleLine } = require("../../src/utils/assStyles.js");
const { loadConfig } = require("../../src/utils/config.js");

const config = loadConfig();

const lessonsPath = path.join(__dirname, "lessons");
const tempPath = path.join(lessonsPath, "temp");
if (!fs.existsSync(tempPath)) {
  fs.mkdirSync(tempPath);
}
const baseImagePath = path.join(__dirname, "tape.gif");

const pauseDuration = 2000;

const Levels = {
  Basic: {
    name: "初级听力",
  },
  Intermediate: {
    name: "中级听力",
  },
  Advanced: {
    name: "高级听力",
  },
};

function createLesson(level, id) {
  const lessonDirPath = path.join(lessonsPath, level, id);
  const lessonAudio = path.join(lessonDirPath, `${id}.mp3`);
  const questionJSON = path.join(lessonDirPath, `question.json`);
  const textJSON = path.join(lessonDirPath, `text.json`);

  const audioDuration = getAudioDuration(lessonAudio);
  // 将baseImagePath变为时长为audioDuration*2的视频，存储在tempPath目录下`${id}_x2.mp4`
  const videoFile = path.join(tempPath, `${id}_x2.mp4`);
  // 修改FFmpeg命令以循环播放GIF直到达到所需时长
  const imageToVideoCommand = `"${FFMPEG_PATH}" -y -loglevel error -stream_loop -1 -i "${baseImagePath}" -c:v libx264 -t ${audioDuration * 2} -pix_fmt yuv420p "${videoFile}"`;
  require("child_process").execSync(imageToVideoCommand);

  const title = `${Levels[level].name} #${id}`;
  // 创建title字幕，位置在100,60,存储在tempPath目录下`${id}_title.ass`，字幕时长为audioDuration*2
  const titleAssFile = path.join(tempPath, `${id}_title.ass`);
  generateTitleASSFile(title, audioDuration * 2, titleAssFile);

  const questions = JSON.parse(fs.readFileSync(questionJSON, "utf8"));
  // 获取第一个问题及答案，创建题目字幕，位置为800,60，字体选择DynaPuff,
  // 存储在tempPath目录下`${id}_questions.ass`，字幕时长为audioDuration*2
  const questionAssFile = path.join(tempPath, `${id}_questions.ass`);
  generateQuestionASSFile(questions, audioDuration, questionAssFile);

  const text = JSON.parse(fs.readFileSync(textJSON, "utf8"));
  // 读取text.json文件，创建文本字幕，位置为1200,60，字体选择DynaPuff,
  // 存储在tempPath目录下`${id}_text.ass`
  // 注意，字幕开始时间为audioDuration + pauseDuration
  const textAssFile = path.join(tempPath, `${id}_text.ass`);
  generateTextASSFile(text, audioDuration, textAssFile);

  const pauseTextAssFile = path.join(tempPath, `${id}_pause_text.ass`);
  generatePauseASSFile("暂停回答问题\\N或者继续对照全文继续听一遍",audioDuration,pauseTextAssFile);

  // 将视频、字幕 合并一个mp4文件，存储在tempPath目录下`${id}.mp4`
  // 先合并标题字幕
  const videoWithTitleFile = path.join(tempPath, `${id}_with_title.mp4`);
  mergeAssVideo(videoFile, titleAssFile, videoWithTitleFile);

  const videoWithTextFile = path.join(tempPath, `${id}_with_text.mp4`);
  mergeAssVideo(videoWithTitleFile, textAssFile, videoWithTextFile);

  // 再合并问题字幕
  const videoWithQuestionFile = path.join(tempPath, `${id}_with_question.mp4`);
  mergeAssVideo(videoWithTextFile, questionAssFile, videoWithQuestionFile);

  console.log("合并暂停字幕...");
  // 合并暂停字幕
  const videoWithPauseTextFile = path.join(tempPath, `${id}_with_pause_text.mp4`);
  mergeAssVideo(videoWithQuestionFile, pauseTextAssFile, videoWithPauseTextFile);

  // 最后合并文本字幕（带音频）
  const videoWithVideo1 = path.join(tempPath, `${id}_with_audio1.mp4`);
  mergeAudioVideo(videoWithPauseTextFile, lessonAudio, videoWithVideo1);

  // 将音频再合并一遍到视频中，音频开始时间为audioDuration + pauseDuration
  const videoFinal = path.join(tempPath, `${id}.mp4`);
  // TODO:
  const startTimeMs = (audioDuration + pauseDuration / 1000) * 1000;
  const delayedAudioCommand = `"${FFMPEG_PATH}" -y -loglevel error -i "${videoWithVideo1}" -i "${lessonAudio}" -filter_complex "[1:a]adelay=delays=${startTimeMs}:all=1[delayedAudio];[0:a][delayedAudio]amix=inputs=2:duration=longest:dropout_transition=0" -c:v copy -c:a aac "${videoFinal}"`;
  console.log(delayedAudioCommand);
  require("child_process").execSync(delayedAudioCommand);
  console.log("视频合并完成✅️");
}

function generateTitleASSFile(title, duration, outputFile) {
  if (duration < 10) {
    duration = "0" + duration;
  }

  const textStyles = config.projectSettings?.textStyles || {};
  let assContent = `[Script Info]
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.601
PlayResX: ${config.projectSettings?.videoWidth || 1920}
PlayResY: ${config.projectSettings?.videoHeight || 1080}

[V4+ Styles]
${generateASSStylesSingleLine(textStyles)}
Style: Title,DynaPuff,72,&HFFFFFF&,${textStyles.color || "&H000000FF"},&H000000&,${textStyles.shadow || "&H80000000"},1,0,0,0,100,100,0,0,1,2,1,1,100,100,1725,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:${typeof duration === "number" ? duration.toFixed(2).padStart(5, "0") : duration},Title,,0,0,0,,${title}
`;

  fs.writeFileSync(outputFile, assContent);
}

function generatePauseASSFile(pauseText, audioDuration, outputFile) {
  const startTime = audioDuration;
  const endTime = audioDuration + pauseDuration / 1000;
  const formatTime = seconds => {
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    const ms = Math.floor((seconds % 1) * 100);
    return `0:${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}.${ms.toString().padStart(2, "0")}`;
  };

  const textStyles = config.projectSettings?.textStyles || {};
  let assContent = `[Script Info]
  Title: Default Aegisub file
  ScriptType: v4.00+
  WrapStyle: 0
  ScaledBorderAndShadow: yes
  YCbCr Matrix: TV.601
  PlayResX: ${config.projectSettings?.videoWidth || 1920}
  PlayResY: ${config.projectSettings?.videoHeight || 1080}
  
  [V4+ Styles]
  ${generateASSStylesSingleLine(textStyles)}
  Style: Title,DynaPuff,72,&H00FF00,${textStyles.color || "&H000000FF"},&H000000&,${textStyles.shadow || "&H80000000"},1,0,0,0,100,100,0,0,1,2,1,1,200,100,700,1
  
  [Events]
  Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
  Dialogue: 0,${formatTime(startTime)},${formatTime(endTime)},Title,,0,0,0,,${pauseText}
  `;

  fs.writeFileSync(outputFile, assContent);
}

function generateQuestionASSFile(questions, duration, outputFile) {
  if (duration < 10) {
    duration = "0" + duration;
  }

  // 取第一个问题
  const firstQuestion = questions.questions[0];
  const questionText = firstQuestion.question;
  const answers = firstQuestion.options.map(option => {
    return `${option.id.toUpperCase()}. ${option.text}`;
  });
  const answerLines = [];
  for (let i = 0; i < answers.length; i++) {
    const start = `Dialogue: 0,0:00:00.00,0:00:`;
    const dur = typeof duration === "number" ? duration.toFixed(2).padStart(5, "0") : duration;
    const line = `${start}${dur},Answers,,0,0,0,,${answers[i]}`;
    answerLines.push(line);
  }

  const textStyles = config.projectSettings?.textStyles || {};
  let assContent = `[Script Info]
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.601
PlayResX: ${config.projectSettings?.videoWidth || 1920}
PlayResY: ${config.projectSettings?.videoHeight || 1080}

[V4+ Styles]
${generateASSStylesSingleLine(textStyles)}
Style: Question,DynaPuff,64,&H00FFFF&,${textStyles.color || "&H000000FF"},&H000000&,${textStyles.shadow || "&H80000000"},1,0,0,0,100,100,0,0,1,2,1,1,300,10,780,1
Style: Answers,DynaPuff,72,&H000000&,${textStyles.color || "&H000000FF"},&H000000&,${textStyles.shadow || "&H80000000"},0,0,0,0,100,100,0,0,1,1,1,1,300,10,460,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:${typeof duration === "number" ? duration.toFixed(2).padStart(5, "0") : duration},Question,,0,0,0,,${questionText}
${answerLines.join("\n")}
`;

  fs.writeFileSync(outputFile, assContent);
}

function generateTextASSFile(textObj, audioDuration, outputFile) {
  const startTime = audioDuration + pauseDuration / 1000;
  const endTime = startTime + audioDuration;

  const formatTime = seconds => {
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    const ms = Math.floor((seconds % 1) * 100);
    return `0:${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}.${ms.toString().padStart(2, "0")}`;
  };

  // 处理对话文本
  const textLines = textObj.dialog.map(d => {
    if (d.text.indexOf(': "') > 0 && d.text.endsWith('"')) {
      return `${d.text.replace('"', "")}`;
    }
    if (d.text.indexOf("A") === 0) {
      return `${d.text}`;
    }
    return `${d.speaker}:${d.text}`;
  });

  const textStyles = config.projectSettings?.textStyles || {};
  const textFontSize = 48;
  let assContent = `[Script Info]
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.601
PlayResX: ${config.projectSettings?.videoWidth || 1920}
PlayResY: ${config.projectSettings?.videoHeight || 1080}

[V4+ Styles]
${generateASSStylesSingleLine(textStyles)}
Style: TextContent,DynaPuff,${textFontSize},&H00FF00&,${textStyles.color || "&H000000FF"},&H000000&,${textStyles.shadow || "&H80000000"},0,0,0,0,100,100,0,0,1,1,1,1,100,10,1200,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
`;
  const start = `Dialogue: 0,${formatTime(startTime)},${formatTime(endTime)},TextContent,,0,0,${400},,`;
  assContent += `${start}`;
  textLines.forEach((line, _index) => {
    //const marginV = 200 + index * 40; // 每行增加40像素垂直间距
    assContent += `${line}\\N`;
  });

  fs.writeFileSync(outputFile, assContent);
}

function main() {
  createLesson("Basic", "100");
}

main();
